package User;

import java.awt.Color;
import java.util.ArrayList;

import MainClass.Game;
import Monster.Monster;
import SubClasses.Direction;
import SubClasses.ObjectInBox;
import SubClasses.Position;
import SubClasses.TypeOfVar;

public class User extends ObjectInBox 
{
	private int Step; // detrmine the speed of the monster - we move the monster each "step" clocks
	private int Quantum;
	public Direction DirectionAxis;
	private Game game;
	private boolean ReturningFlag,UserInBlock,ChasingFlag;
	private ArrayList<Position> UserMoves;
	int firstIndex,lastIndex;  //for Chasing calculations

	public User(int xPos,int yPos,Direction x,int s, int q)
	{
		game = Game.GameBuilder();
		
		Pos_X = xPos;
		Pos_Y= yPos;
				
		DirectionAxis=x;
		
		Step=s; 
		Quantum=q; 
		
		ascii = 'U';
		Forg = Color.BLACK;	
		UserMoves = new ArrayList<Position>();
		ChasingFlag=ReturningFlag=UserInBlock=false;
			
	}
	
	public User(int s, int q)
	{
		game = Game.GameBuilder();
		
		Pos_X = 0;
		Pos_Y= 0;
		
		DirectionAxis=Direction.NONE;
		
		Step=s; 
		Quantum=q; 
		
		ascii = 'U';
		Forg = Color.BLACK;	
		UserMoves = new ArrayList<Position>();
		ChasingFlag=ReturningFlag=UserInBlock=false;

	}
	
	
	public void UpdateNewUserDirection(char scanCode)
	{
		switch(scanCode)
		{
		case 'r':
				if(DirectionAxis!=Direction.RIGHT)
					DirectionAxis=Direction.RIGHT;
				else DirectionAxis=Direction.NONE;
				break;
		case 'l':
			if(DirectionAxis!=Direction.LEFT)
				DirectionAxis=Direction.LEFT;
			else DirectionAxis=Direction.NONE;
				break;
		case 'u': 
			if(DirectionAxis!=Direction.UP)
				DirectionAxis=Direction.UP;
			else DirectionAxis=Direction.NONE;
				break;
		case 'd':	
			if(DirectionAxis!=Direction.DOWN)
				DirectionAxis=Direction.DOWN;
			else DirectionAxis=Direction.NONE;
				break;
		}
	}
	public void UpdateNextUserPosition()
	{
		int i = Pos_X; 
		int j = Pos_Y;
		
		
		if (Quantum  > 0 ) 
		{
		   (Quantum )--;
		   return;
		}
		Quantum  = Step ;
		
		
		if(DirectionAxis==Direction.NONE) return;
		
		if(DirectionAxis==Direction.RIGHT || DirectionAxis==Direction.LEFT )
		{
			j += DirectionAxis.GetValue();
		}
		if(DirectionAxis==Direction.UP || DirectionAxis==Direction.DOWN )
		{
			i += DirectionAxis.GetValue();
		}
		
		if(!game.CheckIndax(i,j))
		{
			return;
		}
		switch (game.getBack(i,j))
		{
			case FrameNotFill:
				if (isReturning())
				{
					game.strike();
					return;
				}
				this.UserMoves.add(new Position(Pos_X,Pos_Y));
				if(!isInBlock()) 
				{
					setInBlock();
					game.SetInBoardValues(Pos_X,Pos_Y,null,TypeOfVar.Empty,TypeOfVar.FrameFill);	
				}
				else game.SetInBoardValues(Pos_X,Pos_Y,null,TypeOfVar.Empty,TypeOfVar.NewLine);			
				break;
			case NewLine:
				if (UserMoves.get(UserMoves.size()-1).isEqual(new Position(i,j)))
				{
					setReturning();
					game.SetInBoardValues(Pos_X,Pos_Y,null,TypeOfVar.Empty,TypeOfVar.FrameNotFill);
					game.setBack(i, j, TypeOfVar.FrameNotFill);
					UserMoves.remove(UserMoves.size()-1);
				}	
				else
					{
					game.strike();
					return;
					}
				break;
			case FrameFill:
				unsetChasing();
				if(isInBlock())
				{		
					unsetInBlock();
					if (!isReturning())
					{
						game.SetInBoardValues(Pos_X,Pos_Y,null,TypeOfVar.Empty,TypeOfVar.NewLine);
						game.FillBlock();	
					}
					else //is returning - no need to use fill block
					{
						UserMoves.clear();
						unsetReturning();
						game.SetInBoardValues(Pos_X,Pos_Y,null,TypeOfVar.Empty,TypeOfVar.FrameNotFill);
						
					}
				}
				else game.SetInBoardValues(Pos_X,Pos_Y,null,TypeOfVar.Empty,TypeOfVar.FrameFill);	
				break;
		default:
			break;
		}
	
	Pos_X =i; 
	Pos_Y=j;
	
	game.SetInBoardValues(Pos_X,Pos_Y,this,TypeOfVar.User,game.getBack(i,j));	
		
		
	}
	
	public void clearUser()
	{
		unsetInBlock();
		unsetReturning();
		unsetChasing();
		game.SetInBoardValues(Pos_X,Pos_Y,null,TypeOfVar.Empty,game.getBack(Pos_X,Pos_Y));
		if (!UserMoves.isEmpty())   UserMoves.remove(0);    //removes first member because it is on Frame
		for (Position pos : UserMoves) 
		{
			game.SetInBoardValues(pos.GetX(),pos.GetY(),null,TypeOfVar.Empty,TypeOfVar.FrameNotFill);
		}
			UserMoves.clear();
	}
	public void placeUserInPosition(int x, int y)
	{
		if (!game.CheckIndax(x, y)) return ;
		if (!game.isFrameFillIndex(x, y)) return;
		clearUser();
		this.Pos_X=x;
		this.Pos_Y=y;
		this.DirectionAxis=Direction.NONE;
		game.SetInBoardValues(Pos_X,Pos_Y,this,TypeOfVar.User,TypeOfVar.FrameFill);
	}
	
	public boolean isInBlock()
	{
		return this.UserInBlock;
	}
	public void setInBlock()
	{
		this.UserInBlock=true;
	}
	
	public void unsetInBlock()
	{
		this.UserInBlock=false;
	}
	
	public boolean isReturning()
	{
		return this.ReturningFlag;
	}
	public void setReturning()
	{
		this.ReturningFlag=true;
	}
	
	public void unsetReturning()
	{
		this.ReturningFlag=false;
	}
	
	
	public boolean isChasing()
	{
		return this.ChasingFlag;
	}
	public void setChasing()
	{
		this.ChasingFlag=true;
	}
	
	public void unsetChasing()
	{
		this.ChasingFlag=false;
	}
	
	public void startChase(int x, int y)
	{
	if (!isChasing())
	{
		Position pos = new Position(x,y);
		this.firstIndex=this.lastIndex=indexOfPositionInArray(pos);
		setChasing();
	}
		
	}
	
	private int indexOfPositionInArray(Position p)
	{
		for (int i=0 ; i< UserMoves.size() ; i++)
			if (p.isEqual(UserMoves.get(i))) return i;
		return -1;
	
	}
	public void updateChsingLine()
	{
		if (isChasing() && (this.Quantum==0 || this.Quantum==this.Step/2) )
		{
			if (lastIndex>=UserMoves.size()-1)
			{
				game.strike();
				return;
			}
			Position p1 = UserMoves.get(lastIndex);
			lastIndex++;
			game.SetInBoardValues(p1.GetX(),p1.GetY(),null,TypeOfVar.Empty,TypeOfVar.ChasingLine);
			if (firstIndex>0)
			{
				Position p2 = UserMoves.get(firstIndex);
				game.SetInBoardValues(p2.GetX(),p2.GetY(),null,TypeOfVar.Empty,TypeOfVar.ChasingLine);
				firstIndex--;
				
			}

		}
	}
}
	


